
/**
 * 关联类型（associated types）让我们可以在 trait 里面增加一个待定义的类型（类型占位符），将类型占位符与 trait 相关联，
 * 这样 trait 的方法签名中就可以使用这些占位符类型。trait 的实现者在实现这个 trait 的时候，会指定一个具体类型，来替换掉这个占位符。
 * 这样，我们可以在一个 trait 中通过占位符使用不同类型，在实现此 trait 时才需要指定这些类型具体是什么
 *
 * 总体上看，这是一个优点意思的特性
 *
 * 这个看起来是不是很像通用类型（泛型）？是的，但是它们还是有区别的。
 */
trait Danger {
    fn happen(&self)->String;
}
struct Fire{
    address: String
}
impl Danger for Fire{
    fn happen(&self)->String {
        //返回address+"燃烧了"
        self.address.clone()+"燃烧了"
    }
}


trait Fight {
    type Item;
    fn attack(&self, other: &Self::Item);
    fn defend<T>(&self, danger: &T)
    where T: Danger; 
}
#[derive(Debug)]
struct Person {
    name: String,
    age: u32,
    sex: String,
}
#[derive(Debug)]
struct Animal {
    name: String,
    age: u32,
}

impl Fight for Person {
    type Item = Animal;
    fn attack(&self, other: &self::Item) {
        println!(
            "{}岁{}(性别:{}) 攻击了 {}岁{}",
            self.age,
            self.name,
            self.sex,
            other.age,
            other.name
        );
    }
    fn defend<T: Danger>(&self, danger: &T) {
        println!("{},{}岁{}(性别:{}) 奋起并力图战胜它们",danger.happen(), self.age, self.name, self.sex);
    }
}

impl Fight for Animal {
    type Item = Person;
    fn attack(&self, other: &Self::Item) {
        println!("{}岁{} 攻击了 {}岁{}", self.age, self.name, other.age, other.name);
    }
    fn defend<T: Danger>(&self, danger: &T) {
        println!("{},{}岁{} 跑了", danger.happen(),self.age, self.name);
    }
}

fn draw_fire() {
    println!("       (  .      )");
    println!("     )           (              )");
    println!("             .  '   .   '  .  '  .");
    println!("    (    , )       (.   )  (   ',    )");
    println!("     .' ) ( . )    ,  ( ,     )   ( .");
    println!("  ). , ( .   (  ) ( , ')  .' (  ,    )");
    println!("  (_,) . ), ) _) _,')  (, ) '. )  ,. (' )");
    println!("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
}

fn draw_girl_face() {
    println!("         _____         ");
    println!("      __/     \\__      ");
    println!("    _/  (o) (o)  \\_    ");
    println!("   /      <       \\   ");
    println!("  |     \\___/      |  ");
    println!("  |   _________    |  ");
    println!("   \\_/         \\__/   ");
    println!("    |  /\\ /\\    |     ");
    println!("    | |  |  |   |     ");
    println!("    | |  |  |   |     ");
    println!("    |  \\/ \\/    |     ");
    println!("     \\        _/      ");
    println!("      \\______/        ");
    println!("        |  |          ");
    println!("        |  |          ");
    println!("        |__|          ");
}

fn main() {
    println!("\n火焰出现了：");
    draw_fire();

    println!("\n沐拉出现了：");
    draw_girl_face();
    
    let lu = Person { name: "沐拉".to_string(), age: 13, sex: "女".to_string() };
    let dog = Animal { name: "小狗".to_string(), age: 3 };
    let fire = Fire{address: "森林".to_string()};
    println!("{:?}", lu);
    println!("{:?}", dog);
    lu.attack(&dog);
    dog.attack(&lu);
    lu.defend(&fire);
    dog.defend(&fire);
}
